Activiti工作流分配组任务的三种方式 - 月光の雲海 - CSDN博客

创建时间:2019/1/25 9:41
来源:https://blog.csdn.net/linhaiyun_ytdx/article/details/81254690


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linhaiyun_ytdx/article/details/81254690

本实例的流程图如下图所示:

1.分配组任务方式一(直接指定办理人)

1.1 该方式为默认方式,流程启动方式和其他流程的启动方式一致

  1. 1
    String processDefinitionKey = "receiveTask"; //流程定义的key
  2. 2
    ProcessInstance pi = processEngine.getRuntimeService() //与正在执行的流程实例和执行对象相关的Service
  3. 3
    .startProcessInstanceByKey(processDefinitionKey);

1.2 流程图中任务节点的配置如下:

1.3 说明

  1. 小A,小B,小C,小D是组任务的办理人
  2. 但是这样分配组任务的办理人不够灵活,因为项目开发中任务的办理人不要放置XML文件中。
  3. act_ru_identitylink表存放任务的办理人,包括个人任务和组任务,表示正在执行的任务
  4. act_hi_identitylink表存放任务的办理人,包括个人任务和组任务,表示历史任务
  1. 1
      区别在于:如果是个人任务TYPE的类型表示participant(参与者)
  2. 2
  3. 3
      如果是组任务TYPE的类型表示candidate(候选者)和participant(参与者)

2.分配个人任务方式二(使用流程变量)

2.1 该流程在启动流程实例时,通过HashMap设置流程变量,赋值给执行的流程实例

  1. 1
    package com.ytdx.groupTask;
  2. 2
  3. 3
    import java.io.InputStream;
  4. 4
    import java.util.HashMap;
  5. 5
    import java.util.List;
  6. 6
    import java.util.Map;
  7. 7
  8. 8
    import org.activiti.engine.ProcessEngine;
  9. 9
    import org.activiti.engine.ProcessEngines;
  10. 10
    import org.activiti.engine.history.HistoricIdentityLink;
  11. 11
    import org.activiti.engine.repository.Deployment;
  12. 12
    import org.activiti.engine.runtime.ProcessInstance;
  13. 13
    import org.activiti.engine.task.IdentityLink;
  14. 14
    import org.activiti.engine.task.Task;
  15. 15
    import org.junit.Test;
  16. 16
  17. 17
    /**
  18. 18
    * 分配个人任务方式二(使用流程变量)
  19. 19
    * @author lhy
  20. 20
    *
  21. 21
    */
  22. 22
    public class TaskTest {
  23. 23
  24. 24
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
  25. 25
  26. 26
    /**
  27. 27
    * 部署流程定义(从inputStream)
  28. 28
    */
  29. 29
    @Test
  30. 30
    public void deploymentProcess_inputStream(){
  31. 31
    InputStream inputStreamBpmn = this.getClass().getClassLoader().getResourceAsStream("GroupTask.bpmn");
  32. 32
    InputStream inputStreamPng = this.getClass().getClassLoader().getResourceAsStream("GroupTask.png");
  33. 33
    Deployment deployment = processEngine.getRepositoryService() //与流程定义和部署对象相关的Service
  34. 34
    .createDeployment() //创建一个部署对象
  35. 35
    .name("组任务一") //添加部署的名称
  36. 36
    .addInputStream("GroupTask.bpmn", inputStreamBpmn)
  37. 37
    .addInputStream("GroupTask.png", inputStreamPng)
  38. 38
    .deploy(); //完成部署
  39. 39
    System.out.println("部署ID:"+deployment.getId());
  40. 40
    System.out.println("部署名称:"+deployment.getName());
  41. 41
    }
  42. 42
  43. 43
    /**
  44. 44
    * 启动流程实例
  45. 45
    */
  46. 46
    @Test
  47. 47
    public void startProcessInstance(){
  48. 48
    String processDefinitionKey = "GroupTask"; //流程定义的key
  49. 49
    /**启动流程实例的同时,设置流程变量,使用流程变量用来指定任务的办理人,对应GroupTask.bpmn文件中#{userIDs}*/
  50. 50
    Map<String, Object> variables = new HashMap<String, Object>();
  51. 51
    variables.put("userIDs", "大大,中中,小小");
  52. 52
    ProcessInstance pi = processEngine.getRuntimeService() //与正在执行的流程实例和执行对象相关的Service
  53. 53
    .startProcessInstanceByKey(processDefinitionKey,variables); //使用流程定义的key启动流程实例,key对应task.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动
  54. 54
    System.out.println("流程实例ID:"+pi.getId());
  55. 55
    System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
  56. 56
    }
  57. 57
  58. 58
    /**
  59. 59
    * 查询当前人的个人任务
  60. 60
    */
  61. 61
    @Test
  62. 62
    public void findPersonalTask(){
  63. 63
    String assignee = "海哥";
  64. 64
    List<Task> list = processEngine.getTaskService() //与正在执行的任务管理相关的Service
  65. 65
    .createTaskQuery() //创建任务查询对象
  66. 66
    /**查询条件(where部分)*/
  67. 67
    .taskAssignee(assignee) //指定个人任务查询,指定办理人
  68. 68
    // .taskCandidateUser(candidateUser) //组任务的办理人查询
  69. 69
    /**排序*/
  70. 70
    .orderByTaskCreateTime().asc() //使用创建时间的升序排列
  71. 71
    /**返回结果集*/
  72. 72
    .list(); //返回列表
  73. 73
  74. 74
    if(list!=null && list.size()>0){
  75. 75
    for(Task task:list){
  76. 76
    System.out.println("任务ID:"+task.getId());
  77. 77
    System.out.println("任务名称:"+task.getName());
  78. 78
    System.out.println("任务的创建时间:"+task.getCreateTime());
  79. 79
    System.out.println("任务的办理人:"+task.getAssignee());
  80. 80
    System.out.println("流程实例ID:"+task.getProcessInstanceId());
  81. 81
    System.out.println("执行对象ID:"+task.getExecutionId());
  82. 82
    System.out.println("流程定义ID:"+task.getProcessDefinitionId());
  83. 83
    System.out.println("########################################################");
  84. 84
    }
  85. 85
    }
  86. 86
    }
  87. 87
  88. 88
    /**
  89. 89
    * 查询当前人的组任务
  90. 90
    */
  91. 91
    @Test
  92. 92
    public void findGroupTask(){
  93. 93
    String candidateUser = "小小";
  94. 94
    List<Task> list = processEngine.getTaskService() //与正在执行的任务管理相关的Service
  95. 95
    .createTaskQuery() //创建任务查询对象
  96. 96
    /**查询条件(where部分)*/
  97. 97
    .taskCandidateUser(candidateUser) //组任务的办理人查询
  98. 98
    /**排序*/
  99. 99
    .orderByTaskCreateTime().asc() //使用创建时间的升序排列
  100. 100
    /**返回结果集*/
  101. 101
    .list(); //返回列表
  102. 102
    if(list!=null && list.size()>0){
  103. 103
    for(Task task:list){
  104. 104
    System.out.println("任务ID:"+task.getId());
  105. 105
    System.out.println("任务名称:"+task.getName());
  106. 106
    System.out.println("任务的创建时间:"+task.getCreateTime());
  107. 107
    System.out.println("任务的办理人:"+task.getAssignee());
  108. 108
    System.out.println("流程实例ID:"+task.getProcessInstanceId());
  109. 109
    System.out.println("执行对象ID:"+task.getExecutionId());
  110. 110
    System.out.println("流程定义ID:"+task.getProcessDefinitionId());
  111. 111
    System.out.println("########################################################");
  112. 112
    }
  113. 113
    }
  114. 114
    }
  115. 115
  116. 116
    /**
  117. 117
    * 完成我的任务
  118. 118
    */
  119. 119
    @Test
  120. 120
    public void completePersonalTask(){
  121. 121
    String taskId = "4905";
  122. 122
    processEngine.getTaskService() //与正在执行的任务管理相关的Service
  123. 123
    .complete(taskId);
  124. 124
    System.out.println("完成任务:任务ID:"+taskId);
  125. 125
    }
  126. 126
  127. 127
    /**
  128. 128
    * 查询正在执行的任务办理人表
  129. 129
    */
  130. 130
    @Test
  131. 131
    public void findRunPersonTask(){
  132. 132
    String taskId = "5205";
  133. 133
    List<IdentityLink> list = processEngine.getTaskService()
  134. 134
    .getIdentityLinksForTask(taskId);
  135. 135
    if(list!=null && list.size()>0){
  136. 136
    for(IdentityLink identityLink:list){
  137. 137
    System.out.println(identityLink.getTaskId()+" "+identityLink.getType()+" "+identityLink.getProcessInstanceId()+" "+identityLink.getUserId());
  138. 138
    }
  139. 139
    }
  140. 140
    }
  141. 141
  142. 142
    /**
  143. 143
    * 查询历史任务的办理人表
  144. 144
    */
  145. 145
    @Test
  146. 146
    public void findHistoryPersonTask(){
  147. 147
    String processInstanceId = "101"; //PROC_INST_ID_ 字段
  148. 148
    List<HistoricIdentityLink> list = processEngine.getHistoryService()
  149. 149
    .getHistoricIdentityLinksForProcessInstance(processInstanceId);
  150. 150
    if(list!=null && list.size()>0){
  151. 151
    for(HistoricIdentityLink identityLink:list){
  152. 152
    System.out.println(identityLink.getTaskId()+" "+identityLink.getType()+" "+identityLink.getProcessInstanceId()+" "+identityLink.getUserId());
  153. 153
    }
  154. 154
    }
  155. 155
    }
  156. 156
  157. 157
    /**
  158. 158
    * 拾取任务,将组任务分给个人任务,指定任务的办理人字段
  159. 159
    */
  160. 160
    @Test
  161. 161
    public void claim(){
  162. 162
    String taskId = "2203"; //任务ID
  163. 163
    String userId = "大大"; //分配的个人任务(可以是组任务中的成员,也可以是非组任务的成员),给字段ASSIGNEE_赋值
  164. 164
    processEngine.getTaskService()
  165. 165
    .claim(taskId, userId);
  166. 166
    }
  167. 167
  168. 168
    /**
  169. 169
    * 将个人任务回退到组任务,前提,之前一定是个组任务
  170. 170
    */
  171. 171
    @Test
  172. 172
    public void setAssigee(){
  173. 173
    String taskId = "2203";
  174. 174
    processEngine.getTaskService()
  175. 175
    .setAssignee(taskId, null);
  176. 176
    }
  177. 177
  178. 178
    /**
  179. 179
    * 向组任务中添加成员(act_hi_identitylink表中查)
  180. 180
    */
  181. 181
    @Test
  182. 182
    public void addGroupUser(){
  183. 183
    String taskId = "2203";
  184. 184
    String userId = "小Y"; //成员办理人
  185. 185
    processEngine.getTaskService()
  186. 186
    .addCandidateUser(taskId, userId);
  187. 187
    }
  188. 188
  189. 189
    /**
  190. 190
    * 从组任务中删除成员
  191. 191
    */
  192. 192
    @Test
  193. 193
    public void deleteGroupUser(){
  194. 194
    String taskId = "2203";
  195. 195
    String userId = "小Y"; //成员办理人
  196. 196
    processEngine.getTaskService()
  197. 197
    .deleteCandidateUser(taskId, userId);
  198. 198
    }
  199. 199
    }

2.2 流程图中任务节点的配置

2.3 说明

  1. 大大,中中,小小是组任务的办理人
  2. 在开发中,可以在页面中指定下一个组任务的办理人,通过流程变量设置下一个任务的办理人

3.分配个人任务方式三(使用类)

3.1 该流程实例在启动时,通过调用监听的TaskListenerImpl类,分配组任务的办理人

  1. 1
    package com.ytdx.groupTask;
  2. 2
  3. 3
    import org.activiti.engine.delegate.DelegateTask;
  4. 4
    import org.activiti.engine.delegate.TaskListener;
  5. 5
  6. 6
    @SuppressWarnings("serial")
  7. 7
    public class TaskListenerImpl implements TaskListener {
  8. 8
  9. 9
    /**
  10. 10
    * 用来指定任务的办理人
  11. 11
    */
  12. 12
    @Override
  13. 13
    public void notify(DelegateTask delegateTask) {
  14. 14
    //指定个人任务的办理人,也可以指定组任务的办理人
  15. 15
    //个人任务:通过类去查询数据库,将下一个任务的办理人查询获取,然后通过setAssignee()的方法指定任务的办理人
  16. 16
    //delegateTask.setAssignee("海哥");
  17. 17
    //组任务:
  18. 18
    delegateTask.addCandidateUser("郭靖");
  19. 19
    delegateTask.addCandidateUser("黄蓉");
  20. 20
    }
  21. 21
  22. 22
    }
  1. 1
    package com.ytdx.groupTask;
  2. 2
  3. 3
    import java.io.InputStream;
  4. 4
    import java.util.List;
  5. 5
  6. 6
    import org.activiti.engine.ProcessEngine;
  7. 7
    import org.activiti.engine.ProcessEngines;
  8. 8
    import org.activiti.engine.history.HistoricIdentityLink;
  9. 9
    import org.activiti.engine.repository.Deployment;
  10. 10
    import org.activiti.engine.runtime.ProcessInstance;
  11. 11
    import org.activiti.engine.task.IdentityLink;
  12. 12
    import org.activiti.engine.task.Task;
  13. 13
    import org.junit.Test;
  14. 14
  15. 15
    /**
  16. 16
    * 分配个人任务方式二(使用类)
  17. 17
    * @author lhy
  18. 18
    *
  19. 19
    */
  20. 20
    public class GroupTaskTest {
  21. 21
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
  22. 22
  23. 23
    /**
  24. 24
    * 部署流程定义(从inputStream)
  25. 25
    */
  26. 26
    @Test
  27. 27
    public void deploymentProcess_inputStream(){
  28. 28
    InputStream inputStreamBpmn = this.getClass().getClassLoader().getResourceAsStream("GroupTasks.bpmn");
  29. 29
    InputStream inputStreamPng = this.getClass().getClassLoader().getResourceAsStream("GroupTasks.png");
  30. 30
    Deployment deployment = processEngine.getRepositoryService() //与流程定义和部署对象相关的Service
  31. 31
    .createDeployment() //创建一个部署对象
  32. 32
    .name("组任务二") //添加部署的名称
  33. 33
    .addInputStream("GroupTasks.bpmn", inputStreamBpmn)
  34. 34
    .addInputStream("GroupTasks.png", inputStreamPng)
  35. 35
    .deploy(); //完成部署
  36. 36
    System.out.println("部署ID:"+deployment.getId());
  37. 37
    System.out.println("部署名称:"+deployment.getName());
  38. 38
    }
  39. 39
  40. 40
    /**
  41. 41
    * 启动流程实例
  42. 42
    */
  43. 43
    @Test
  44. 44
    public void startProcessInstance(){
  45. 45
    String processDefinitionKey = "GroupTasks"; //流程定义的key
  46. 46
    ProcessInstance pi = processEngine.getRuntimeService() //与正在执行的流程实例和执行对象相关的Service
  47. 47
    .startProcessInstanceByKey(processDefinitionKey); //使用流程定义的key启动流程实例,key对应task.bpmn文件中id的属性值,使用key值启动,默认是按照最新版本的流程定义启动
  48. 48
    System.out.println("流程实例ID:"+pi.getId());
  49. 49
    System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
  50. 50
    }
  51. 51
  52. 52
    /**
  53. 53
    * 查询当前人的个人任务
  54. 54
    */
  55. 55
    @Test
  56. 56
    public void findPersonalTask(){
  57. 57
    String assignee = "郭靖";
  58. 58
    List<Task> list = processEngine.getTaskService() //与正在执行的任务管理相关的Service
  59. 59
    .createTaskQuery() //创建任务查询对象
  60. 60
    /**查询条件(where部分)*/
  61. 61
    .taskAssignee(assignee) //指定个人任务查询,指定办理人
  62. 62
    // .taskCandidateUser(candidateUser) //组任务的办理人查询
  63. 63
    /**排序*/
  64. 64
    .orderByTaskCreateTime().asc() //使用创建时间的升序排列
  65. 65
    /**返回结果集*/
  66. 66
    .list(); //返回列表
  67. 67
  68. 68
    if(list!=null && list.size()>0){
  69. 69
    for(Task task:list){
  70. 70
    System.out.println("任务ID:"+task.getId());
  71. 71
    System.out.println("任务名称:"+task.getName());
  72. 72
    System.out.println("任务的创建时间:"+task.getCreateTime());
  73. 73
    System.out.println("任务的办理人:"+task.getAssignee());
  74. 74
    System.out.println("流程实例ID:"+task.getProcessInstanceId());
  75. 75
    System.out.println("执行对象ID:"+task.getExecutionId());
  76. 76
    System.out.println("流程定义ID:"+task.getProcessDefinitionId());
  77. 77
    System.out.println("########################################################");
  78. 78
    }
  79. 79
    }
  80. 80
    }
  81. 81
    /**
  82. 82
    * 查询当前人的组任务
  83. 83
    */
  84. 84
    @Test
  85. 85
    public void findMyGroupTask(){
  86. 86
    String candidateUser = "郭靖";
  87. 87
    List<Task> list = processEngine.getTaskService() //与正在执行的任务管理相关的Service
  88. 88
    .createTaskQuery() //创建任务查询对象
  89. 89
    /**查询条件(where部分)*/
  90. 90
    .taskCandidateUser(candidateUser) //组任务的办理人查询
  91. 91
    /**排序*/
  92. 92
    .orderByTaskCreateTime().asc() //使用创建时间的升序排列
  93. 93
    /**返回结果集*/
  94. 94
    .list(); //返回列表
  95. 95
    if(list!=null && list.size()>0){
  96. 96
    for(Task task:list){
  97. 97
    System.out.println("任务ID:"+task.getId());
  98. 98
    System.out.println("任务名称:"+task.getName());
  99. 99
    System.out.println("任务的创建时间:"+task.getCreateTime());
  100. 100
    System.out.println("任务的办理人:"+task.getAssignee());
  101. 101
    System.out.println("流程实例ID:"+task.getProcessInstanceId());
  102. 102
    System.out.println("执行对象ID:"+task.getExecutionId());
  103. 103
    System.out.println("流程定义ID:"+task.getProcessDefinitionId());
  104. 104
    System.out.println("########################################################");
  105. 105
    }
  106. 106
    }
  107. 107
    }
  108. 108
  109. 109
    /**
  110. 110
    * 完成我的任务
  111. 111
    */
  112. 112
    @Test
  113. 113
    public void completePersonalTask(){
  114. 114
    String taskId = "6404";
  115. 115
    processEngine.getTaskService() //与正在执行的任务管理相关的Service
  116. 116
    .complete(taskId);
  117. 117
    System.out.println("完成任务:任务ID:"+taskId);
  118. 118
    }
  119. 119
  120. 120
    /**
  121. 121
    * 查询正在执行的任务办理人表
  122. 122
    */
  123. 123
    @Test
  124. 124
    public void findRunPersonTask() {
  125. 125
    String taskId = "6704";
  126. 126
    List<IdentityLink> list = processEngine.getTaskService().getIdentityLinksForTask(taskId);
  127. 127
    if (list != null && list.size() > 0) {
  128. 128
    for (IdentityLink identityLink : list) {
  129. 129
    System.out.println(identityLink.getTaskId() + " " + identityLink.getType() + " "
  130. 130
    + identityLink.getProcessInstanceId() + " " + identityLink.getUserId());
  131. 131
    }
  132. 132
    }
  133. 133
    }
  134. 134
  135. 135
    /**
  136. 136
    * 查询历史任务的办理人表
  137. 137
    */
  138. 138
    @Test
  139. 139
    public void findHistoryPersonTask(){
  140. 140
    String processInstanceId = "6704";
  141. 141
    List<HistoricIdentityLink> list = processEngine.getHistoryService()//
  142. 142
    .getHistoricIdentityLinksForProcessInstance(processInstanceId);
  143. 143
    if(list!=null && list.size()>0){
  144. 144
    for(HistoricIdentityLink identityLink:list){
  145. 145
    System.out.println(identityLink.getTaskId()+" "+identityLink.getType()+" "+identityLink.getProcessInstanceId()+" "+identityLink.getUserId());
  146. 146
    }
  147. 147
    }
  148. 148
    }
  149. 149
  150. 150
    /**
  151. 151
    * 拾取任务,将组任务分给个人任务,指定任务的办理人字段
  152. 152
    * 拾取之后,便可从查询当前人的个人任务中查询
  153. 153
    */
  154. 154
    @Test
  155. 155
    public void claim(){
  156. 156
    String taskId = "6704";
  157. 157
    //分配的个人任务(可以是组任务中的成员,也可以是非组任务的成员)
  158. 158
    String userId = "郭靖";
  159. 159
    processEngine.getTaskService()
  160. 160
    .claim(taskId, userId);
  161. 161
    }
  162. 162
  163. 163
    /**
  164. 164
    * 将个人任务回退到组任务,前提,之前一定是个组任务
  165. 165
    */
  166. 166
    @Test
  167. 167
    public void setAssigee(){
  168. 168
    String taskId = "6704";
  169. 169
    processEngine.getTaskService()
  170. 170
    .setAssignee(taskId, null);
  171. 171
    }
  172. 172
  173. 173
    /**
  174. 174
    * 向组任务中添加成员(在表act_ru_identitylink中添加)
  175. 175
    */
  176. 176
    @Test
  177. 177
    public void addGroupUser(){
  178. 178
    //任务ID
  179. 179
    String taskId = "6704";
  180. 180
    String userId = "大H";
  181. 181
    processEngine.getTaskService()
  182. 182
    .addCandidateUser(taskId, userId);
  183. 183
    }
  184. 184
  185. 185
    /**
  186. 186
    * 从组任务中删除成员
  187. 187
    */
  188. 188
    @Test
  189. 189
    public void deleteGroupUser(){
  190. 190
    String taskId = "6704";
  191. 191
    String userId = "大H";
  192. 192
    processEngine.getTaskService()
  193. 193
    .deleteCandidateUser(taskId, userId);
  194. 194
    }
  195. 195
    }

3.2 流程图中任务节点的配置

3.3 说明

  1. 在类中使用delegateTask.addCandidateUser (userId);的方式分配组任务的办理人,此时孙悟空和猪八戒是下一个任务的办理人。
  2. 通过processEngine.getTaskService().claim (taskId, userId);将组任务分配给个人任务,也叫认领任务,即指定某个人去办理这个任务,此时由如来去办理任务。
  3. addCandidateUser()即向组任务添加成员,deleteCandidateUser()即删除组任务的成员。
  4. 在开发中,可以将每一个任务的办理人规定好,例如张三的领导是李四和王五,这样张三提交任务,由李四或者王五去查询组任务,可以看到对应张三的申请,李四或王五再通过认领任务(claim)的方式,由某个人去完成这个任务。

注意:认领任务的时候,可以是组任务成员中的人,也可以不是组任务成员的人,此时通过Type的类型为participant来指定任务的办理人

4.总结

  1. 1
    组任务及三种分配方式:
  2. 2
    1:在taskProcess.bpmn中直接写 candidate-users=“小A,小B,小C,小D"
  3. 3
    2:在taskProcess.bpmn中写 candidate-users =“#{userIDs}”,变量的值要是String的。
  4. 4
    使用流程变量指定办理人
  5. 5
    Map<String, Object> variables = new HashMap<String, Object>();
  6. 6
    variables.put("userIDs", "大大,小小,中中");
  7. 7
    3: 使用TaskListener接口,使用类实现该接口,在类中定义:
  8. 8
  9. 9
    delegateTask.addCandidateUser(userId1); //添加组任务的用户
  10. 10
    delegateTask.addCandidateUser(userId2);
  11. 11
    组任务分配给个人任务(认领任务):
  12. 12
    processEngine.getTaskService().claim(taskId, userId);
  13. 13
    个人任务分配给组任务:
  14. 14
    processEngine.getTaskService(). setAssignee(taskId, null);
  15. 15
    向组任务添加人员:
  16. 16
    processEngine.getTaskService().addCandidateUser(taskId, userId);
  17. 17
    向组任务删除人员:
  18. 18
    processEngine.getTaskService().deleteCandidateUser(taskId, userId);
  19. 19
    个人任务和组任务存放办理人对应的表:
  20. 20
    act_ru_identitylink表存放任务的办理人,包括个人任务和组任务,表示正在执行的任务
  21. 21
    act_hi_identitylink表存放任务的办理人,包括个人任务和组任务,表示历史任务
  22. 22
    区别在于:如果是个人任务TYPE的类型表示participant(参与者)
  23. 23
    如果是组任务TYPE的类型表示candidate(候选者)和participant(参与者)